Skip to content

refactor: modularize vite.config.ts and fix Windows script compatibility#379

Open
facusturla wants to merge 1267 commits intokoala73:mainfrom
facusturla:refactor/modular-vite-windows-fix
Open

refactor: modularize vite.config.ts and fix Windows script compatibility#379
facusturla wants to merge 1267 commits intokoala73:mainfrom
facusturla:refactor/modular-vite-windows-fix

Conversation

@facusturla
Copy link
Contributor

This PR addresses two maintenance and developer experience issues:

  1. Windows Script Compatibility (Fixes TODO-005):
    • Replaced direct environment variable assignments in package.json with cross-env.
    • This ensures scripts like npm run dev:tech and npm run build:finance work correctly on Windows PowerShell/CMD.
    • Verified locally on a Windows environment.
  2. Vite Configuration Modularization:
    • Refactored the monolithic 1,200-line vite.config.ts into a modular structure under a new vite/ directory.
    • Extracted logic into:
      • vite/variants.ts: Site variant metadata.
      • vite/proxy.ts: Proxy rules for APIs and RSS feeds.
      • vite/plugins.ts: Custom Vite plugins (Sebuf, RSS proxy, etc.).
    • This significantly improves readability and makes the build pipeline easier to maintain as the project grows.
      Verified the changes by running both npm run dev:tech and a full production npm run build after the refactor.

koala73 and others added 30 commits February 19, 2026 19:33
- Use for...of entries() instead of index-based loops in summarization.ts
  to satisfy strict noUncheckedIndexedAccess (7 TS18048/TS2345 errors)
- Replace fragile API_PROVIDERS[1] with .find(p => p.name === groq)
- Add OLLAMA_API_URL and OLLAMA_MODEL to SUPPORTED_SECRET_KEYS in main.rs
  so keychain secrets are injected into sidecar on desktop startup
…and Ollama UX

- Split settings window into 3 tabs: LLMs (Ollama/Groq/OpenRouter),
  API Keys (data feeds), and Debug & Logs
- Add featureFilter option to RuntimeConfigPanel for rendering subsets
- Consolidate keychain to single JSON vault entry (1 macOS prompt vs 20)
- Add Ollama model discovery with /api/tags + /v1/models fallback
- Strip <think> reasoning tokens from Ollama responses
- Suppress thinking with think:false in Ollama request body
- Parallel secret verification with 15s global timeout
- Fix manual model input overlapping dropdown (CSS grid-area + hidden-input class)
- Add loading spinners to settings tab panels
- Suppress notification popups when settings window is open
- Filter embed models from Ollama dropdown
- Fix settings window black screen flash with inline dark background
Add local LLM support mentions across feature descriptions, talking
points, screenshot suggestions, and changelog. New dedicated section
for Ollama/LM Studio as feature koala73#11.
DeckGLMap: guard updateLayers/debounce/raf against null maplibreMap,
null out references in destroy() to prevent post-destroy setProps crash.

main.ts: filter contentWindow.postMessage (Facebook WebView),
vertex shader compile (GPU driver), objectStoreNames (iOS background),
Unexpected identifier https (Safari 16), _0x obfuscated vars (extensions),
WKWebView deallocated (Tauri lifecycle).
…koala73#124)

## Summary

Extracts shared summarization logic (CORS, validation, caching, prompt
building) into a reusable `_summarize-handler.js` factory, then uses it
to add Ollama as the first provider in the fallback chain. This reduces
code duplication across Groq, OpenRouter, and the new Ollama endpoint
while maintaining identical behavior.

**Fallback chain is now:** Ollama → Groq → OpenRouter → Browser T5

## Type of change

- [x] New feature
- [x] Refactor / code cleanup
- [x] API endpoints (`/api/*`)

## Affected areas

- [x] AI Insights / World Brief
- [x] Desktop app (Tauri)
- [x] API endpoints (`/api/*`)
- [x] Config / Settings

## Changes

### New Files
- **`api/_summarize-handler.js`** – Shared handler factory with:
- `createSummarizeHandler(providerConfig)` – Creates edge handlers for
any LLM provider
- `getCacheKey()` – Stable cache key generation (extracted from
per-provider code)
- `deduplicateHeadlines()` – Headline deduplication logic (extracted
from per-provider code)
- Unified prompt building for brief/analysis/translate modes with
tech/full variants
  - CORS, validation, caching, and error handling pipeline

- **`api/ollama-summarize.js`** – New Ollama endpoint (34 lines):
- Calls local/remote Ollama instance via OpenAI-compatible
`/v1/chat/completions`
  - Reads `OLLAMA_API_URL` and `OLLAMA_MODEL` from environment
  - Shares Redis cache with Groq/OpenRouter (same cache key strategy)
  - Returns fallback signal when unconfigured or API fails

- **`api/ollama-summarize.test.mjs`** – Unit tests for Ollama endpoint:
  - Fallback signal when `OLLAMA_API_URL` not configured
  - Success response with provider="ollama"
  - Error handling (API errors, empty responses)
  - Model selection via `OLLAMA_MODEL` env

- **`api/_summarize-handler.test.mjs`** – Unit tests for shared factory:
  - Cache key stability and variation by mode/variant/lang/geoContext
  - Headline deduplication logic
  - Handler creation with missing credentials
  - API provider calls and response shaping

- **`tests/summarization-chain.test.mjs`** – Integration tests for
fallback chain:
  - Ollama success short-circuits (no downstream calls)
  - Ollama failure → Groq success
  - Both fail → fallback signals propagate

### Modified Files

**`api/groq-summarize.js`** & **`api/openrouter-summarize.js`**
- Replaced ~290 lines of duplicated logic with single call to
`createSummarizeHandler()`
- Now thin wrappers: 26 lines (Groq) and 28 lines (OpenRouter)
- Identical behavior, zero functional changes

**`src/services/summarization.ts`**
- Updated fallback chain: `Ollama → Groq → OpenRouter → Browser T5`
- Refactored `tryGroq()` and `tryOpenRouter()` into unified
`tryApiProvider()` function
- Added `API_PROVIDERS` config array for provider ordering
- Updated `SummarizationProvider` type to include `'ollama'`

**`src-tauri/sidecar/local-api-server.mjs`**
- Added `OLLAMA_API_URL` and `OLLAMA_MODEL` to `ALLOWED_ENV_KEYS`
- Added validation for `OLLAMA_API_URL` in
`validateSecretAgainstProvider()`:
  - Probes `/v1/models` (OpenAI-compatible endpoint)
  - Falls back to `/api/tags` (native Ollama endpoint)
- Returns "Ollama endpoint verified" or "Ollama endpoint verified
(native API
…buffers

Toggling cables/pipelines off then on caused deck.gl assertion failure
because the cached PathLayer had its WebGL resources destroyed on removal.
…keychain vault

- Ollama/LM Studio integration with auto model discovery and 4-tier fallback chain
- Settings window split into LLMs, API Keys, and Debug tabs
- Consolidated keychain vault (1 OS prompt instead of 20+)
- README expanded with privacy architecture, summarization chain docs
- CHANGELOG updated with full v2.5.0 release notes
- 5 new defense/intel RSS feeds, Koeberg nuclear plant added
Removes circular dev→prod dependency. The new polymarketPlugin()
mirrors the edge function logic locally: validates params, fetches
from gamma-api.polymarket.com, and gracefully returns [] when
Cloudflare JA3 blocks server-side TLS (expected behavior).
The Vite dev plugin was hardcoding `{ videoId: null }` with a TODO,
causing LiveNewsPanel to never resolve actual live streams during local
development. Replace the stub with the same fetch-and-scrape approach
used by the production edge function (api/youtube/live.js): fetch the
channel's /live page and extract videoId + isLive from the HTML.

https://claude.ai/code/session_01684qa7XvS7sf9CShqU8zNg
Store the interval ID returned by setInterval in a new clockIntervalId
field and clear it in App.destroy(). Previously, the interval was never
stored or cleared, causing DOM writes to double on each Vite HMR reload.

https://claude.ai/code/session_0111CXxXM5qKR83UAdUTQDyL
npm install regenerated the lockfile to reflect the current
version (2.5.0) and license field from package.json.

https://claude.ai/code/session_01684qa7XvS7sf9CShqU8zNg
…eived load

Inline a minimal HTML skeleton (header bar, map placeholder, panels grid)
with critical CSS directly in index.html so the page shows a structured
layout immediately instead of a blank screen while JavaScript boots.

- Dark theme skeleton with hardcoded colors matching CSS variables
- Light theme support via [data-theme="light"] selectors
- Shimmer animation on placeholder lines for visual feedback
- 6 skeleton panels in a responsive grid matching the real layout
- Map section with radial gradient matching the map background
- Skeleton is automatically replaced when App.renderLayout() sets innerHTML
- Marked aria-hidden="true" for screen reader accessibility

Expected gain: perceived load time drops to <0.5s.

https://claude.ai/code/session_01Fxk8GMRn2cEUq3ThC2a8e5
Replace the static LOCALE_LOADERS map (14 explicit dynamic imports) with
import.meta.glob for lazy loading. English is now statically imported as
the always-needed fallback; all other 13 locales are loaded on demand.

- Statically import en.json so it's bundled eagerly (no extra fetch)
- Use import.meta.glob with negative pattern to lazy-load non-English
  locales only when the user actually switches language
- Add manualChunks rule to prefix lazy locale chunks with `locale-`
- Exclude locale-*.js from service worker precache via globIgnores
- Add CacheFirst runtime caching for locale files when loaded on demand

SW precache reduced from 43 entries (5587 KiB) to 29 entries (4840 KiB),
saving ~747 KiB from the initial download.

https://claude.ai/code/session_01TfRgC5GWsv51swxRSGxxeJ
Audit and fix localization coverage gaps across 12 components that
were using hardcoded English strings instead of the i18next t() system.

Components fixed:
- IntelligenceGapBadge.ts: context menu label
- InvestmentsPanel.ts: filters, table headers, sector labels, statuses
- Panel.ts: aria-label, resize tooltip, settings button
- LanguageSelector.ts: aria-label
- ServiceStatusPanel.ts: loading state, category filters, status labels
- TechEventsPanel.ts: tab labels, stats, badges
- StrategicRiskPanel.ts: risk metrics, section titles, time formatting
- RegulationPanel.ts: dashboard title, tabs, section headers, stances
- TechReadinessPanel.ts: fetching state indicators, source attribution
- InsightsPanel.ts: progress steps, empty states
- VerificationChecklist.ts: all UI labels and verdict text
- LiveNewsPanel.ts: offline/error messages

Added ~150 new translation keys to en.json and propagated them
as English placeholders to all 13 other locale files.

https://claude.ai/code/session_018UKmgomYsVsEmJfX7Ava3v
Convert VERIFICATION_TEMPLATE module-level constant to
getVerificationTemplate() function to defer t() calls, and add
8 new i18n keys for checklist item labels.

https://claude.ai/code/session_018UKmgomYsVsEmJfX7Ava3v
Add contain: content to the .panel class so the browser knows that
layout changes inside a panel don't affect siblings. The .panel-content
class already has contain: layout style for scroll performance.

Expected gain: faster layout recalculations during panel updates.

https://claude.ai/code/session_01E9FpgiebjEuUPhNt8mwX9U
Add will-change: transform, opacity to dragged panels, signal modal,
and mobile warning modal. Add will-change: transform to map markers
and map popup sheet. Remove will-change via animationend/transitionend
listeners after one-shot animations complete to free GPU memory.

https://claude.ai/code/session_01DDhT6Ex596eX1CtSb6mHdH
Fix ignoreErrors regex for unsafe-eval CSP violations — word order
didn't match actual error messages. Add filter for "Unexpected end of
input" from truncated WebView script loads.
Fixes:
- Linux AppImage black screen on WebKit/GStreamer (koala73#411)
- Destroy live news player before showing offline/error message (koala73#410)
Launch the built AppImage under Xvfb after the Linux build to catch
startup crashes and render failures automatically. Uploads a screenshot
artifact for visual inspection.
…oala73#414)

The squash merge of koala73#413 put smoke test steps into build-desktop.yml
instead of the intended standalone workflow. This commit:
- Reverts build-desktop.yml to its original state
- Adds test-linux-app.yml as a separate Linux-only smoke test workflow
@facusturla facusturla force-pushed the refactor/modular-vite-windows-fix branch 2 times, most recently from 545bd31 to 66b8095 Compare February 26, 2026 13:31
@facusturla
Copy link
Contributor Author

Thanks for the thorough review! I've addressed all the feedback:

BLOCKING fixes:

  1. package-lock.json peer churn — I restored the lock file from main and re-ran npm install to only add the cross-env dependency. However, my local npm version (v11.6.2) still produces some peer flag differences compared to the upstream lock. If you'd prefer a completely clean lock, please regenerate it on your end with your CI npm version after merging the source changes.

  2. __dirname fix — Replaced resolve() with fileURLToPath(new URL('.', import.meta.url)).

  3. proxyConfig(process) leak — Removed the process: any parameter; process.env is accessed directly (it's a global in Node).

SUGGESTION fixes: Converted all vite/*.ts files from 4-space to 2-space to match project convention. Exported a VariantMeta interface from variants.tsand imported it in plugins.ts. Replaced double cross-env calls with cross-env-shell for all chained scripts.

Verified locally: npm run build passes (tsc + vite build in ~40s).

* fix(ci): use weston+XWayland for Linux smoke test instead of pure Wayland

Previous attempt used GDK_BACKEND=wayland which caused GTK init panic
(tao requires X11). Now: weston headless with XWayland provides X11
through a real compositor. Falls back to Xvfb if weston fails.
Also uploads weston/app logs as artifacts for debugging.

* refactor(ci): use xwfb-run for Linux smoke test display

xwfb-run (from xwayland-run package) is purpose-built for this:
Xwayland on a headless Wayland compositor, replaces xvfb-run.
Falls back to plain Xvfb if xwfb-run is unavailable.
Uploads display-server and app logs as artifacts.
Only run CI on PRs from branches within the repo, not from external
forks. Prevents unnecessary action minutes from contributor PRs.
* ci(linux): add AppImage smoke test to desktop build

Launch the built AppImage under Xvfb after the Linux build to catch
startup crashes and render failures automatically. Uploads a screenshot
artifact for visual inspection.

* Optimize Wingbits API usage and panel polling
…oala73#419)

Linux had no keyring backend feature enabled — keyring v3 fell back to
in-memory mock store. Secrets appeared to save but were lost on restart.

Added `linux-native-sync-persistent` (kernel keyutils + D-Bus Secret
Service combo) and `crypto-rust` for Secret Service encryption. This
uses GNOME Keyring or KDE Wallet on desktop Linux for persistent storage.
…ala73#424)

* chore: bump v2.5.12

## Changelog

- fix(linux): enable keyring persistence via Secret Service + keyutils (koala73#419)
- fix(ci): use weston+XWayland for Linux smoke test (koala73#417)
- ci: add standalone Test Linux App workflow (koala73#414)
- ci: skip Typecheck and Lint on fork PRs (koala73#415)
- perf: optimize Wingbits API usage and reduce unnecessary polling (koala73#416)

* fix(linux): append host GStreamer plugins to AppImage search path

The linuxdeploy GStreamer hook force-overrides GST_PLUGIN_PATH_1_0 and
GST_PLUGIN_SYSTEM_PATH_1_0 to only contain bundled plugins from the CI
build system (Ubuntu 24.04, GStreamer 1.24).  On hosts with newer
GStreamer (e.g. Arch 1.28), codec plugins like gst-libav and
fakevideosink from gst-plugins-bad are invisible — WebKit can't play
video.

Append common host GStreamer plugin directories as fallback so the
system's codec plugins are discoverable while bundled plugins retain
priority.

Also fixes:
- tauri.conf.json devUrl port mismatch (5173 → 3000) breaking desktop:dev
- live-channels-window YouTube validation allowing add on non-OK responses
…channels (koala73#425)

The /api/youtube/live validation endpoint may return 429 or non-JSON
responses (Vercel WAF, YouTube rate limiting). Previously this caused
res.json() to parse HTML → either throw (caught, channel added) or
return channelExists:false (blocked add with red border).

Now only blocks when the API explicitly returns 200 OK with
channelExists:false — any non-OK status or error allows the add.

Also bumps version to 2.5.13.
- CI: add ubuntu-24.04-arm matrix entry with aarch64-unknown-linux-gnu
- Node sidecar: download linux-arm64 Node.js bundle for ARM runners
- Download API: add linux-appimage-arm64 pattern for aarch64 AppImage
- Download banner: show both x64 and ARM64 Linux options (UA can't distinguish)
- Desktop updater: map Linux aarch64 to linux-appimage-arm64 for in-app updates
- Smoke test: fix AppImage search path for cross-target builds
Changes since v2.5.13:
- feat: add ARM64 Linux build target and download detection (koala73#427)
- fix(live-channels): tolerate YouTube API failures when adding custom channels (koala73#425)
- fix(linux): append host GStreamer plugins to AppImage search path (koala73#424)
- fix(linux): enable keyring persistence via Secret Service + keyutils (koala73#419)
…rrors (koala73#429)

- Widen beforeSend regex to catch `null is not an object (evaluating 'u.id')`
  pattern from deck.gl internals during variant switch (WORLDMONITOR-4A, 270 events)
- Remove `in_app` requirement from TypeError suppression — Sentry SDK marks
  deck.gl/maplibre frames inconsistently, causing the filter to miss
- Fix Firefox lexical declaration wording: `can't access` vs Chrome's `Cannot access`
- Add noise filters: isReCreate (Android WebView injection), HTMLImageElement
  style access, WebGL context loss write access
…3#430)

* fix(sentry): tighten noise filters for deck.gl/maplibre and WebView errors

- Widen beforeSend regex to catch `null is not an object (evaluating 'u.id')`
  pattern from deck.gl internals during variant switch (WORLDMONITOR-4A, 270 events)
- Remove `in_app` requirement from TypeError suppression — Sentry SDK marks
  deck.gl/maplibre frames inconsistently, causing the filter to miss
- Fix Firefox lexical declaration wording: `can't access` vs Chrome's `Cannot access`
- Add noise filters: isReCreate (Android WebView injection), HTMLImageElement
  style access, WebGL context loss write access

* fix: reduce upstream API pressure with cache TTL optimization

- Military/posture: 5min → 15min (flight cache, theater posture, panel refresh, intelligence refresh)
- Theater posture: fetch 2 targeted bbox regions instead of global states/all (~95% less data)
- Wingbits batch: reduce from 20 to 10, sequential with 100ms delay instead of Promise.all burst
- Preserve intelligenceCache.military across intelligence refresh cycles
- OpenSky edge proxy: add CDN caching (s-maxage=120), align timeout to 20s
- list-military-flights: Redis cache 2min → 10min
- Market handlers: stablecoins/crypto/commodities/sectors 3min → 5min
- Cable health: 3min → 10min
- YouTube embed: s-maxage 60s → 15min
…oala73#431)

Both ubuntu-24.04 (x64) and ubuntu-24.04-arm (ARM64) upload a smoke
test screenshot with the static name `linux-smoke-test-screenshot`.
upload-artifact@v4 rejects duplicate names with 409 Conflict.

Append matrix.label so each gets a unique artifact name.

CI log proof: run 22452393753 shows the ARM64 "Upload smoke test
screenshot" step failing on the exact artifact name collision.
…oala73#434)

AppImage only bundled gst-plugins-base and gst-plugins-good, missing
H.264/AAC (gst-libav), x264 (plugins-ugly), AV1 (plugins-bad), and
GL video sink (gst-gl). YouTube's MSE player checks codec support
via MediaSource.isTypeSupported() — WebKitGTK delegates to GStreamer
and reports no compatible decoders, showing "can't play this video".

Add plugins-bad, plugins-ugly, gst-libav, and gst-gl to CI install
so bundleMediaFramework includes them in the AppImage.
…ala73#435)

* fix(linux): bundle full GStreamer codec suite for YouTube playback

AppImage only bundled gst-plugins-base and gst-plugins-good, missing
H.264/AAC (gst-libav), x264 (plugins-ugly), AV1 (plugins-bad), and
GL video sink (gst-gl). YouTube's MSE player checks codec support
via MediaSource.isTypeSupported() — WebKitGTK delegates to GStreamer
and reports no compatible decoders, showing "can't play this video".

Add plugins-bad, plugins-ugly, gst-libav, and gst-gl to CI install
so bundleMediaFramework includes them in the AppImage.

* feat: support YouTube URLs in custom channels, add Middle East region

- Parse YouTube watch URLs and channel URLs in the custom channel input
  (watch?v=, youtu.be/, @handle URLs all supported)
- Auto-resolve channel/video names via YouTube oembed proxy
- Add video ID lookup endpoint to api/youtube/live.js
- Return channelName from channel live detection API
- Add Middle East region tab (Al Hadath, Sky News Arabia, TRT World,
  Iran International, CGTN Arabic)
- Add BBC News and France 24 English to Europe region
- Rename NASA TV to Sen Space Live
- Add i18n keys (youtubeHandleOrUrl, regionMiddleEast) to all 17 locales
Copy link
Owner

@koala73 koala73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: Modularize vite.config.ts + Windows script compatibility

Overall

Good direction — splitting a 690-line config into focused modules improves readability. cross-env for Windows compat is the right tool. Several issues need addressing before merge.


BLOCKING

1. RSS_PROXY_ALLOWED_DOMAINS in vite/plugins.ts is ~62 domains behind api/rss-proxy.js

The dev-server RSS proxy plugin has its own hardcoded domain allowlist that has drifted massively from the production source of truth (api/rss-proxy.js). Missing domains include all euronews locales, Indian/Greek/LatAm/African regional sources, many international news outlets added over recent months, and happy-variant sources like dailygood.org, goodgoodgood.co, etc.

Also adds www.huffpost.com which doesn't exist in production.

This creates a situation where feeds work in production but fail silently in dev (403 from the proxy), making debugging painful.

Suggested fix: Import the domain list from a shared constant, or — simpler — just import/re-use from api/rss-proxy.js. Having two copies guarantees drift.

2. sebufApiPlugin path resolution changed from relative imports to resolve(serverRoot, ...)

Current code uses:

import('./server/router')
import('./src/generated/server/worldmonitor/seismology/v1/service_server')

PR changes to:

import(resolve(serverRoot, 'server/router'))
import(resolve(serverRoot, 'src/generated/server/worldmonitor/seismology/v1/service_server'))

Where serverRoot = fileURLToPath(new URL('.', import.meta.url)) which resolves to the project root. These should be equivalent, but dynamic import() with resolve() paths bypasses Vite's module graph — meaning HMR invalidation of server modules may not work correctly. The existing file watcher (server.watcher.on('change', ...)) nullifies cachedRouter, but Vite won't track the import dependencies. This is a functional regression risk for dev experience.

3. __dirname polyfill is unnecessary and subtly wrong

const __dirname = fileURLToPath(new URL('.', import.meta.url));

Vite already provides __dirname in config files via its CJS compatibility layer. The existing code on main uses __dirname directly without any polyfill (lines 815-845). This shadows the built-in with a manually constructed version. While the value should be identical, it's unnecessary complexity.


SUGGESTIONS

4. cross-env-shell quoting may break on some Windows shells

Scripts like:

"build:full": "cross-env-shell VITE_VARIANT=full \"tsc && vite build\""

The nested escaped quotes work in most cases but are fragile with some Windows terminal emulators. Consider testing on actual Windows (cmd.exe, PowerShell, Git Bash).

5. Missing newline at end of package.json

The diff shows \ No newline at end of file — the trailing newline was removed. This causes unnecessary git noise on the next edit.

6. Comments stripped from vite.config.ts

Several useful comments were removed during the refactor (e.g., "Geospatial bundles are expected to be large", "onnxruntime-web ships a minified browser bundle", "Give lazy-loaded locale chunks a recognizable prefix"). These explain non-obvious decisions. The manualChunks one-liners are less readable without them.

7. process.env.FRED_API_KEY in vite/proxy.ts leaks server env into proxy config

The FRED proxy rewrite function reads process.env.FRED_API_KEY directly. This works but means the proxy config function is impure (depends on env state at call time). Consider passing it as a parameter or documenting the dependency.


Summary

The modularization structure is good. The main blocker is the RSS domain list drift (62+ missing domains) — this will cause dev/prod parity issues. The sebufApiPlugin path resolution change needs testing to confirm HMR still works. Fix those two and this is ready to merge.

koala73 and others added 5 commits February 26, 2026 22:49
Add X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security,
Content-Security-Policy, Referrer-Policy, and Permissions-Policy headers
to all routes via vercel.json catch-all pattern.
- Indian Express (India section) → asia region
- India News Network (diplomacy) → asia region
- The War Zone → updated to direct feed (was Google News proxy)
- gCaptain (maritime/waterways) → intel sources
- Added domains to RSS proxy allowlist
…malize indentation, type activeMeta, use cross-env-shell
…ths, remove __dirname polyfill

- Extract RSS allowed domains into shared api/rss-allowed-domains.js
  (single source of truth for both prod and dev proxy)
- Revert sebufApiPlugin to relative import() paths for Vite module graph compat
- Remove unnecessary __dirname polyfill (Vite provides it natively)
- Restore explanatory comments in manualChunks/onwarn
- Document FRED_API_KEY env dependency in proxy.ts
- Restore trailing newline in package.json
@facusturla facusturla force-pushed the refactor/modular-vite-windows-fix branch from 5ae50dd to 635722f Compare February 26, 2026 19:10
@facusturla
Copy link
Contributor Author

Addresses PR review feedback

Blocking fixes

1. RSS domain drift resolved — Created api/rss-allowed-domains.js as a shared
single source of truth. Both api/rss-proxy.js (production) and vite/plugins.ts
(dev proxy) now import from this file. ~62 missing domains restored, spurious
www.huffpost.com removed. Two copies can never drift again.
2. sebufApiPlugin path resolution reverted — Changed back from
import(resolve(serverRoot, '...')) to relative import('./...'), matching the
original main branch pattern. This restores Vite's module graph tracking so HMR
correctly invalidates server modules. The serverRoot parameter was removed from
the function signature.
3. __dirname polyfill removed — Removed the manual
const __dirname = fileURLToPath(new URL('.', import.meta.url)) and its
import { fileURLToPath } from 'url'. Vite provides __dirname natively in
config files via its CJS compatibility layer.

Suggestions addressed

4. cross-env-shell quoting — The nested escaped quotes
(cross-env-shell VITE_VARIANT=full \"tsc && vite build\") follow the
recommended pattern from the cross-env docs. Tested on Windows PowerShell
and cmd.exe. Git Bash also works since cross-env handles the normalization.
5. package.json trailing newline — Restored the missing \n at EOF.
6. Explanatory comments restored — Added back three comments that explain
non-obvious build decisions:

  • // Geospatial bundles are expected to be large even when split.
  • // onnxruntime-web ships a minified browser bundle that intentionally uses eval.
  • // Give lazy-loaded locale chunks a recognizable prefix so the service-worker can glob-ignore them.
    7. FRED_API_KEY env dependency documented — Added a note in vite/proxy.ts
    that FRED_API_KEY is read from process.env at proxy-creation time and must
    be set in .env before starting the dev server.

Rebase note

Rebased onto latest main (fe413fa). Conflict in api/rss-proxy.js was
straightforward — upstream still had the inline domain array while our branch
replaces it with an import from the new shared api/rss-allowed-domains.js.
Resolved by keeping the import-based approach. No upstream domain additions
were lost — the shared file was built from upstream's complete list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.